gusucode.com > VC 简洁的tooltip提示类 > VC 简洁的tooltip提示类/gusucode/MFECToolTip.cpp
//Download by http://www.NewXing.com // Author: Ferdinand V. Abne // Email : fabne@bigfoot.com // Revision History: // July 16, 1998 - Creation #include "stdafx.h" #include "MFECToolTip.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMFECToolTip CMFECToolTip::CMFECToolTip() { m_nHeight = 0; m_nWidth = 0; m_nFontSize = 14; // original size m_currentControlID = 0; m_pParentWnd = NULL; m_aControlInfo.RemoveAll(); } CMFECToolTip::~CMFECToolTip() { ToolTipInfo *pInfo = NULL; int nSize = m_aControlInfo.GetSize(); for( int i = 0; i < nSize; i++ ) { pInfo = (ToolTipInfo*)m_aControlInfo.GetAt( i ); delete pInfo; } m_aControlInfo.RemoveAll(); } void CMFECToolTip::Create(CWnd* pWnd) { m_pParentWnd = pWnd; } void CMFECToolTip::ErasePreviousToolTipDisplay( UINT nControlID ) { //This assertion fails because you did not call Create() first. //m_pParentWnd was not initialized. ASSERT(m_pParentWnd); //if erase already, do not do it again if((m_nHeight == 0) || (m_nWidth == 0)) return; CRect oInfoRect(0,0,0,0); CalculateInfoBoxRect(nControlID, &oInfoRect); m_pParentWnd->InvalidateRect(&oInfoRect); m_pParentWnd->UpdateWindow(); m_nHeight = 0; m_nWidth = 0; } void CMFECToolTip::CalculateHeightAndWidth(CStringArray& straInfos) { //This assertion fails because you did not call Create() first. //m_pParentWnd was not initialized. ASSERT(m_pParentWnd); int nMaxLength = 0; int nLength; int nLine = straInfos.GetSize(); m_nTotalLine = nLine; // holder for maximum line of information for(int i=0; i<nLine; i++) { nLength = (straInfos[i]).GetLength(); if(nLength > nMaxLength) nMaxLength = nLength; } m_maxCharInLine = nMaxLength; // holder for longest char info m_nHeight = 12 + nLine * (m_nFontSize - 1); //m_nFontSize is the font size m_nWidth = 10 + (int)(7.5 * nMaxLength); //aproximately 5 pixel per char } void CMFECToolTip::CalculateInfoBoxRect(UINT nControlID, CRect* pInfoRect) { ASSERT(m_pParentWnd); CRect oRect(0,0,0,0); CRect oParentWindowRect(0,0,0,0); m_pParentWnd->GetWindowRect(&oParentWindowRect); m_pParentWnd->ScreenToClient(&oParentWindowRect); CWnd* pWnd = m_pParentWnd->GetDlgItem(nControlID); ASSERT(pWnd); pWnd->GetWindowRect(&oRect); m_pParentWnd->ScreenToClient(&oRect); //check if the box fit in the parent dialog SetFontSize( 14 ); int nBottom = oRect.bottom - ((oRect.bottom - oRect.top)/2) + m_nHeight; if(nBottom <= oParentWindowRect.bottom) { pInfoRect->top = oRect.bottom - (oRect.bottom - oRect.top)/2; pInfoRect->bottom = pInfoRect->top + m_nHeight; } else { // change the size of the font as well as the info box if all // info data cannot be viewed if( m_nHeight > (oParentWindowRect.bottom - oParentWindowRect.top) ) { SetFontSize( 12 ); m_nHeight = 12 + m_nTotalLine * (m_nFontSize - 1); //m_nFontSize is the font size m_nWidth = 10 + (int)(7 * m_maxCharInLine); } // end pInfoRect->bottom = oParentWindowRect.bottom - 1; pInfoRect->top = pInfoRect->bottom - m_nHeight; } //check if the box fit in the parent dialog int nRight = (oRect.left + oRect.right)/2 + m_nWidth; if(nRight <= oParentWindowRect.right) { pInfoRect->left = (oRect.left + oRect.right)/2; pInfoRect->right = pInfoRect->left + m_nWidth; } else { int nLeft = (oRect.left + oRect.right)/2 - m_nWidth; if(nLeft <= oParentWindowRect.left) { pInfoRect->left = oParentWindowRect.left + 1; pInfoRect->right = pInfoRect->left + m_nWidth; } else { pInfoRect->right = (oRect.left + oRect.right)/2; pInfoRect->left = pInfoRect->right - m_nWidth; } } ASSERT(pInfoRect->top <= pInfoRect->bottom); ASSERT(pInfoRect->left <= pInfoRect->right); } void CMFECToolTip::ShowToolTip( UINT nControlID ) { ToolTipInfo *pToolTip = IsControlIDExisting( nControlID ); if( pToolTip == NULL ) return; DisplayInfo( pToolTip ); } void CMFECToolTip::ShowToolTip( CPoint& point ) { CWnd* pWnd = m_pParentWnd->ChildWindowFromPoint(point); if( pWnd ) { UINT nControlID = (UINT)pWnd->GetDlgCtrlID(); if( m_currentControlID != nControlID ) { ErasePreviousToolTipDisplay( m_currentControlID ); ShowToolTip( nControlID ); } } } void CMFECToolTip::DisplayInfo( ToolTipInfo* pToolTip ) { if( pToolTip->nInfoSize <= 0 ) return; ASSERT(m_pParentWnd); CDC* pDC = m_pParentWnd->GetDC(); CRect oInfoRect; CBrush oBrush, *pOldBrush, oBorderBrush; int nX, nY; TEXTMETRIC TM; int nTextHigh; CFont oFont, *pOldFont; CWnd* pWnd = NULL; pDC->SetBkMode(TRANSPARENT); oBrush.CreateSolidBrush( pToolTip->nBackColor ); pOldBrush = pDC->SelectObject( &oBrush ); pDC->SetTextColor( pToolTip->nTextColor ); //calculate the width and height of the box dynamically CalculateHeightAndWidth( pToolTip->nControlInfo ); CalculateInfoBoxRect( pToolTip->nControlID, &oInfoRect ); oFont.CreateFont(m_nFontSize, 0, 0, 0, FW_REGULAR, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New"); pOldFont = pDC->SelectObject(&oFont); pDC->FillRect(&oInfoRect, &oBrush); pDC->SelectObject(pOldBrush); oBrush.DeleteObject(); oBorderBrush.CreateSolidBrush( pToolTip->nTextColor ); pOldBrush = pDC->SelectObject(&oBorderBrush); DrawEdge(pDC->m_hDC, &oInfoRect, BDR_RAISEDINNER | BDR_SUNKENOUTER, BF_RECT); pDC->SetTextAlign(TA_LEFT); pDC->GetTextMetrics(&TM); nTextHigh = TM.tmHeight + TM.tmExternalLeading - 2; nX = oInfoRect.left + 8; nY = oInfoRect.top + 5; for( register UINT i = 0; i < pToolTip->nInfoSize; i++) { pDC->TextOut(nX, nY, pToolTip->nControlInfo[i]); nY += m_nFontSize - 1; } pDC->SelectObject(pOldBrush); oBorderBrush.DeleteObject(); m_pParentWnd->ReleaseDC(pDC); } BOOL CMFECToolTip::AddControlInfo( UINT contolID, CStringArray& straInfo, COLORREF back, COLORREF text ) { ToolTipInfo *pToolTip = new ToolTipInfo; ASSERT( pToolTip != NULL ); int nSize = straInfo.GetSize(); if( pToolTip <= 0 ) // no information, don't add to the list and return FALSE { delete pToolTip; return FALSE; } pToolTip->nControlInfo.RemoveAll(); pToolTip->nInfoSize = nSize; pToolTip->nControlID = contolID; for( register int i = 0; i < nSize; i++ ) { pToolTip->nControlInfo.Add( straInfo[i] ); } // initialize colors, use default if not supplied pToolTip->nBackColor = back; pToolTip->nTextColor = text; // add to the list m_aControlInfo.Add( pToolTip ); return TRUE; } ToolTipInfo* CMFECToolTip::IsControlIDExisting( UINT controlID ) { ToolTipInfo *pToolTip = NULL; int nSize = m_aControlInfo.GetSize(); for( register int i = 0; i < nSize; i++ ) { pToolTip = (ToolTipInfo*)m_aControlInfo.GetAt( i ); if( pToolTip->nControlID == controlID ) // if found! { m_currentControlID = controlID; return pToolTip; } } m_currentControlID = 0; // if not found, reset the current control ID to refresh the display return NULL; } BOOL CMFECToolTip::RemoveControlInfo( UINT controlID ) { ToolTipInfo *pToolTip = NULL; int nSize = m_aControlInfo.GetSize(); for( register int i = 0; i < nSize; i++ ) { pToolTip = (ToolTipInfo*)m_aControlInfo.GetAt( i ); if( pToolTip->nControlID == controlID ) // if found! { if( m_currentControlID == controlID ) ErasePreviousToolTipDisplay( m_currentControlID ); m_aControlInfo.RemoveAt( i ); // remove the entry delete pToolTip; break; // break from the loop } } return TRUE; }